﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using AjaxStack.Support;

namespace AjaxStack.Handlers
{
	public class HtmlHandler : IHttpHandler
	{
		private static readonly Regex RemoveWhiteSpace 
			= new Regex(@"(?<=[^])\t{2,}|(?<=[>])\s{2,}(?=[<])|(?<=[>])\s{2,11}(?=[<])|(?=[\n])\s{2,}", RegexOptions.Compiled);

		public void ProcessRequest(HttpContext context)
		{
			context.Response.ContentType = "text/javascript";

			if (context.Request["writeFile"] != null)
			{
				context.Response.Write("File was written to: " + WriteAppPages());
			}
			else
			{
				var jsText = GetPagesAsJavascript("~/html/".MapHostAbsolutePath());
				context.Response.Write(jsText);
				context.Response.End();
			}
		}

		public static void WriteAllPages()
		{
			WriteAppPages();
		}

		public static string WriteAppPages()
		{
			var absolutePath = "~/html/".MapHostAbsolutePath();
			if (!Directory.Exists(absolutePath)) return null;

			var jsText = GetPagesAsJavascript(absolutePath);
			var appPagesPath = "~/js/App/AppPages.js".MapHostAbsolutePath();
			File.WriteAllText(appPagesPath, jsText);

			return appPagesPath;
		}

		public static string GetPagesAsJavascript(string webAppAbsolutePath)
		{
			if (!Directory.Exists(webAppAbsolutePath)) return null;

			var pageBuilder = new StringBuilder();
			pageBuilder.Append("function AppPages(app){ \nthis.app = app; \nthis.pages = {}; ");
			foreach (var htmlFilePath in Directory.GetFiles(webAppAbsolutePath, "*.htm"))
			{
				if (htmlFilePath.InHiddenDirectory()) continue;

				//Can be optimized
				var htmlFileText = File.ReadAllText(htmlFilePath);
				var htmlFileName = Path.GetFileNameWithoutExtension(htmlFilePath);

				pageBuilder.AppendFormat("\nthis.pages['{0}'] = function(data){{ return ", htmlFileName);

				htmlFileText = RemoveWhiteSpace.Replace(htmlFileText, string.Empty);
				htmlFileText = htmlFileText.Replace("\r", string.Empty);
				htmlFileText = htmlFileText.Replace("\n", string.Empty);

				var sb = new StringBuilder();
				var templateParts = htmlFileText.Split(new[] { "${" }, StringSplitOptions.RemoveEmptyEntries);
				foreach (var templatePart in templateParts)
				{
					if (sb.Length > 0)
					{
						sb.Append(" + ");
					}
					var variableExpressionEndIndex = templatePart.IndexOf("}");
					if (templateParts.Length > 1 && variableExpressionEndIndex != -1)
					{
						var variableName = templatePart.Substring(0, variableExpressionEndIndex);
						if (variableName.IndexOf(".") == -1)
						{
							variableName = "data." + variableName;
						}
						var remainingText = templatePart.Substring(variableExpressionEndIndex + 1).Replace("'", @"\'");
						sb.AppendFormat("\n{0} + '{1}'", variableName, remainingText);
					}
					else
					{
						var escapedHtmlText = templatePart.Replace(@"\", @"\\").Replace("'", @"\'");
						sb.AppendFormat("'{0}'", escapedHtmlText);
					}
				}

				pageBuilder.Append(sb.ToString());
				pageBuilder.AppendLine(" };"); //end this.pages
			}
			pageBuilder.Append("}"); //end AppPages

			return pageBuilder.ToString();
		}

		public bool IsReusable
		{
			get
			{
				return false;
			}
		}
	}

}